package com.killcalorie.wjduan.auth

import com.killcalorie.wjduan.auth.dto.*

import com.killcalorie.wjduan.auth.config.JwtUtil

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException

import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.web.bind.annotation.*


@RestController
@RequestMapping("/api/auth")
class AuthenticationController( private val userRepository: UserRepository,
    private val passwordEncoder: PasswordEncoder,
    private val jwtUtil: JwtUtil,
    private val userDetailsService : AuthenticationService,
    private val authenticationManager: AuthenticationManager) {

    // @Autowired
    // private lateinit var authenticationManager: AuthenticationManager

    // @Autowired
    // private lateinit var passwordEncoder: PasswordEncoder

    // @Autowired
    // private lateinit var userDetailsService: AuthenticationService

    // @Autowired
    // private lateinit var jwtUtil: JwtUtil

    // @Autowired
    // private lateinit var userRepository: UserRepository



    @GetMapping("/hello")
    fun hello(): String {
        return "Harfan here"
    }

    @GetMapping("/checkUser")
    fun checkUser(): String {
        val authentication =
            SecurityContextHolder.getContext().authentication
        return authentication.name
    }


    //curl -X POST --location "http://localhost:8080/api/auth/authenticate" -H "Content-Type: application/json" -d "{ \"username\":\"wjduan\@linx.com\",\"password\": \"Hello\" }"
    @PostMapping("/authenticate")
    fun authenticate(@RequestBody authenticationRequest: AuthenticationRequest): ResponseEntity<*> {
        authenticationManager.authenticate(
            UsernamePasswordAuthenticationToken(
                authenticationRequest.username,
                authenticationRequest.password
            )
        )
        val userDetails: UserDetails = authenticationRequest.username.let { userDetailsService.loadUserByUsername(it) }!!
        val jwt = jwtUtil.generateToken(userDetails)
        return ResponseEntity.ok<Any>(AuthenticationResponse(jwt))
    }

    //curl -X POST --location "http://localhost:8080/api/auth/signin" -H "Content-Type: application/json" -d "{ \"email\":\"wjduan@linx.com\",\"password\": \"Hello\" }"
    @PostMapping("/signin")
    fun authenticateUser(@RequestBody loginRequest: LoginRequest): ResponseEntity<*> {
        try {
            val authentication = authenticationManager.authenticate(
                UsernamePasswordAuthenticationToken(
                    loginRequest.email,
                    loginRequest.password
                )
            )
            SecurityContextHolder.getContext().authentication = authentication

            // 加载用户详情
            val userDetails = userDetailsService.loadUserByUsername(loginRequest.email)!!
       
            val jwt = jwtUtil.generateToken(userDetails)
            // val responseBody = AuthenticationResponse(loginRequest.email)
            val responseHeaders = HttpHeaders()
            responseHeaders.add("Authorization", jwt)
            return ResponseEntity.ok().headers(responseHeaders).body(ApiResponse(true,"${jwt}"))
        } catch(e: UsernameNotFoundException){
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponse(false, "Authentication failed: invalid username"))
        } catch(e: Exception) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(ApiResponse(false, "Authentication failed: ${e.message}"))
        }
    }


    //curl -X POST --location "http://localhost:8080/api/auth/signup" -H "Content-Type: application/json" -d "{ \"email\":\"wjduan@linx.com\",\"password\": \"Hello\" }"
    @PostMapping("/signup")
    fun registerUser(@RequestBody signUpRequest: SignUpRequest): ResponseEntity<*> {
        // 检查用户是否已存在
        val existingUser = userRepository.findUserByEmail(signUpRequest.email)
        if (existingUser != null) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ApiResponse(false, "Email already registered"))
        }

        // Creating user's account
        val jwtUser = UserAuth(null, signUpRequest.email, passwordEncoder.encode(signUpRequest.password))
        jwtUser.let { userRepository.save(it) }
        return ResponseEntity.ok<Any>(ApiResponse(true, "User registered successfully"))
    }

    @PostMapping("/logout")
    fun logout(@RequestHeader("Authorization") authorizationHeader: String): ResponseEntity<String> {
        val jwtToken = authorizationHeader
        jwtUtil.invalidateToken(jwtToken)
        return ResponseEntity.ok("Logged out successfully.")
    }
}